//! 交易工具模块
//! 
//! 提供交易相关的工具函数

use serde::{Deserialize, Serialize};
use crate::objects::{RawBar, Operate, Direction};

/// 交易工具配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradeConfig {
    /// 最大仓位比例
    pub max_position_ratio: f64,
    /// 止损比例
    pub stop_loss_ratio: f64,
    /// 止盈比例
    pub take_profit_ratio: f64,
    /// 风险控制开关
    pub risk_control_enabled: bool,
}

/// 交易信号
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradeSignal {
    /// 操作类型
    pub operate: Operate,
    /// 价格
    pub price: f64,
    /// 数量
    pub quantity: f64,
    /// 信号强度
    pub strength: f64,
    /// 时间戳
    pub timestamp: i64,
}

/// 交易工具
#[derive(Debug, Clone)]
pub struct TradeUtils {
    config: TradeConfig,
}

impl TradeUtils {
    /// 创建新的交易工具
    pub fn new(config: TradeConfig) -> Self {
        Self { config }
    }

    /// 生成移动平均交叉信号
    pub fn ma_cross_signal(&self, fast_ma: &[f64], slow_ma: &[f64]) -> Vec<TradeSignal> {
        if fast_ma.len() != slow_ma.len() || fast_ma.len() < 2 {
            return vec![];
        }
        
        let mut signals = Vec::new();
        
        for i in 1..fast_ma.len() {
            let prev_fast = fast_ma[i-1];
            let prev_slow = slow_ma[i-1];
            let curr_fast = fast_ma[i];
            let curr_slow = slow_ma[i];
            
            // 金叉：快线上穿慢线
            if prev_fast <= prev_slow && curr_fast > curr_slow {
                signals.push(TradeSignal {
                    operate: Operate::Long,
                    price: curr_fast,
                    quantity: 1.0,
                    strength: (curr_fast - curr_slow) / curr_slow,
                    timestamp: i as i64,
                });
            }
            // 死叉：快线下穿慢线
            else if prev_fast >= prev_slow && curr_fast < curr_slow {
                signals.push(TradeSignal {
                    operate: Operate::Short,
                    price: curr_fast,
                    quantity: 1.0,
                    strength: (curr_slow - curr_fast) / curr_slow,
                    timestamp: i as i64,
                });
            }
        }
        
        signals
    }

    /// 生成RSI超买超卖信号
    pub fn rsi_signal(&self, rsi_values: &[f64], oversold: f64, overbought: f64) -> Vec<TradeSignal> {
        if rsi_values.len() < 2 {
            return vec![];
        }
        
        let mut signals = Vec::new();
        
        for i in 1..rsi_values.len() {
            let prev_rsi = rsi_values[i-1];
            let curr_rsi = rsi_values[i];
            
            // 超卖反弹
            if prev_rsi <= oversold && curr_rsi > oversold {
                signals.push(TradeSignal {
                    operate: Operate::Long,
                    price: 0.0, // 需要从价格数据获取
                    quantity: 1.0,
                    strength: (curr_rsi - oversold) / (100.0 - oversold),
                    timestamp: i as i64,
                });
            }
            // 超买回落
            else if prev_rsi >= overbought && curr_rsi < overbought {
                signals.push(TradeSignal {
                    operate: Operate::Short,
                    price: 0.0, // 需要从价格数据获取
                    quantity: 1.0,
                    strength: (overbought - curr_rsi) / overbought,
                    timestamp: i as i64,
                });
            }
        }
        
        signals
    }

    /// 生成MACD信号
    pub fn macd_signal(&self, macd_line: &[f64], signal_line: &[f64]) -> Vec<TradeSignal> {
        if macd_line.len() != signal_line.len() || macd_line.len() < 2 {
            return vec![];
        }
        
        let mut signals = Vec::new();
        
        for i in 1..macd_line.len() {
            let prev_macd = macd_line[i-1];
            let prev_signal = signal_line[i-1];
            let curr_macd = macd_line[i];
            let curr_signal = signal_line[i];
            
            // MACD金叉
            if prev_macd <= prev_signal && curr_macd > curr_signal {
                signals.push(TradeSignal {
                    operate: Operate::Long,
                    price: 0.0,
                    quantity: 1.0,
                    strength: (curr_macd - curr_signal).abs(),
                    timestamp: i as i64,
                });
            }
            // MACD死叉
            else if prev_macd >= prev_signal && curr_macd < curr_signal {
                signals.push(TradeSignal {
                    operate: Operate::Short,
                    price: 0.0,
                    quantity: 1.0,
                    strength: (curr_signal - curr_macd).abs(),
                    timestamp: i as i64,
                });
            }
        }
        
        signals
    }

    /// 计算仓位大小
    pub fn calculate_position_size(&self, capital: f64, risk_per_trade: f64, stop_loss: f64, entry_price: f64) -> f64 {
        if stop_loss == 0.0 || entry_price == 0.0 {
            return 0.0;
        }
        
        let risk_amount = capital * risk_per_trade;
        let price_risk = (entry_price - stop_loss).abs();
        let position_size = risk_amount / price_risk;
        
        // 应用最大仓位限制
        let max_position = capital * self.config.max_position_ratio;
        position_size.min(max_position)
    }

    /// 计算止损价格
    pub fn calculate_stop_loss(&self, entry_price: f64, direction: Direction, atr: f64) -> f64 {
        match direction {
            Direction::Up => entry_price - (atr * self.config.stop_loss_ratio),
            Direction::Down => entry_price + (atr * self.config.stop_loss_ratio),
        }
    }

    /// 计算止盈价格
    pub fn calculate_take_profit(&self, entry_price: f64, direction: Direction, atr: f64) -> f64 {
        match direction {
            Direction::Up => entry_price + (atr * self.config.take_profit_ratio),
            Direction::Down => entry_price - (atr * self.config.take_profit_ratio),
        }
    }

    /// 风险控制检查
    pub fn risk_control_check(&self, current_position: f64, max_position: f64, current_drawdown: f64, max_drawdown: f64) -> bool {
        if !self.config.risk_control_enabled {
            return true;
        }
        
        // 检查仓位限制
        if current_position >= max_position {
            return false;
        }
        
        // 检查回撤限制
        if current_drawdown >= max_drawdown {
            return false;
        }
        
        true
    }

    /// 计算夏普比率
    pub fn calculate_sharpe_ratio(&self, returns: &[f64], risk_free_rate: f64) -> f64 {
        if returns.is_empty() {
            return 0.0;
        }
        
        let mean_return: f64 = returns.iter().sum::<f64>() / returns.len() as f64;
        let variance: f64 = returns.iter()
            .map(|r| (r - mean_return).powi(2))
            .sum::<f64>() / returns.len() as f64;
        let std_dev = variance.sqrt();
        
        if std_dev == 0.0 {
            return 0.0;
        }
        
        (mean_return - risk_free_rate) / std_dev
    }

    /// 计算最大回撤
    pub fn calculate_max_drawdown(&self, equity_curve: &[f64]) -> f64 {
        if equity_curve.is_empty() {
            return 0.0;
        }
        
        let mut max_equity = equity_curve[0];
        let mut max_drawdown = 0.0;
        
        for &equity in equity_curve {
            if equity > max_equity {
                max_equity = equity;
            }
            let drawdown = (max_equity - equity) / max_equity;
            if drawdown > max_drawdown {
                max_drawdown = drawdown;
            }
        }
        
        max_drawdown
    }

    /// 计算胜率
    pub fn calculate_win_rate(&self, trades: &[TradeSignal]) -> f64 {
        if trades.is_empty() {
            return 0.0;
        }
        
        let winning_trades = trades.iter()
            .filter(|trade| trade.strength > 0.0)
            .count();
        
        winning_trades as f64 / trades.len() as f64
    }

    /// 生成交易报告
    pub fn generate_trade_report(&self, signals: &[TradeSignal], bars: &[RawBar]) -> serde_json::Value {
        let total_signals = signals.len();
        let long_signals = signals.iter().filter(|s| s.operate == Operate::Long).count();
        let short_signals = signals.iter().filter(|s| s.operate == Operate::Short).count();
        
        let avg_strength: f64 = if !signals.is_empty() {
            signals.iter().map(|s| s.strength).sum::<f64>() / signals.len() as f64
        } else {
            0.0
        };
        
        let max_strength = signals.iter().map(|s| s.strength).fold(0.0, f64::max);
        let min_strength = signals.iter().map(|s| s.strength).fold(f64::INFINITY, f64::min);
        
        serde_json::json!({
            "total_signals": total_signals,
            "long_signals": long_signals,
            "short_signals": short_signals,
            "signal_statistics": {
                "avg_strength": avg_strength,
                "max_strength": max_strength,
                "min_strength": min_strength
            },
            "risk_control": {
                "enabled": self.config.risk_control_enabled,
                "max_position_ratio": self.config.max_position_ratio,
                "stop_loss_ratio": self.config.stop_loss_ratio,
                "take_profit_ratio": self.config.take_profit_ratio
            },
            "data_points": bars.len()
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ma_cross_signal() {
        let config = TradeConfig {
            max_position_ratio: 0.1,
            stop_loss_ratio: 0.02,
            take_profit_ratio: 0.04,
            risk_control_enabled: true,
        };
        let trade_utils = TradeUtils::new(config);
        
        let fast_ma = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        let slow_ma = vec![2.0, 2.5, 3.5, 3.0, 4.0];
        let signals = trade_utils.ma_cross_signal(&fast_ma, &slow_ma);
        
        assert!(!signals.is_empty());
        assert_eq!(signals[0].operate, Operate::Long);
    }

    #[test]
    fn test_rsi_signal() {
        let config = TradeConfig {
            max_position_ratio: 0.1,
            stop_loss_ratio: 0.02,
            take_profit_ratio: 0.04,
            risk_control_enabled: true,
        };
        let trade_utils = TradeUtils::new(config);
        
        let rsi_values = vec![30.0, 35.0, 70.0, 75.0, 30.0];
        let signals = trade_utils.rsi_signal(&rsi_values, 30.0, 70.0);
        
        assert!(!signals.is_empty());
    }

    #[test]
    fn test_calculate_position_size() {
        let config = TradeConfig {
            max_position_ratio: 0.1,
            stop_loss_ratio: 0.02,
            take_profit_ratio: 0.04,
            risk_control_enabled: true,
        };
        let trade_utils = TradeUtils::new(config);
        
        let position_size = trade_utils.calculate_position_size(10000.0, 0.02, 95.0, 100.0);
        assert!(position_size > 0.0);
    }

    #[test]
    fn test_calculate_max_drawdown() {
        let config = TradeConfig {
            max_position_ratio: 0.1,
            stop_loss_ratio: 0.02,
            take_profit_ratio: 0.04,
            risk_control_enabled: true,
        };
        let trade_utils = TradeUtils::new(config);
        
        let equity_curve = vec![100.0, 110.0, 105.0, 120.0, 115.0];
        let max_dd = trade_utils.calculate_max_drawdown(&equity_curve);
        
        assert!(max_dd >= 0.0);
        assert!(max_dd <= 1.0);
    }
} 